package service

import (
	"context"
	"errors"
	"math/rand"
	"time"

	"gitee.com/zhyclouds/fable-scribe/internal/domain"
	"gitee.com/zhyclouds/fable-scribe/internal/repository"
	"github.com/dlclark/regexp2"
	"golang.org/x/crypto/bcrypt"
)

var (
	ErrDuplicateUsername         = repository.ErrDuplicateUsername
	ErrInvalidUsernameOrPassword = errors.New("用户不存在或密码不对")
)

// 密码正则表达式：必须包含字母、数字、特殊字符，并且不少于八位
const passwordRegexPattern = `^(?=.*[A-Za-z])(?=.*\d)(?=.*[$@$!%*#?&])[A-Za-z\d$@$!%*#?&]{8,}$`

// UserService 用户服务接口
type UserService interface {
	Register(ctx context.Context, username, password string) (domain.User, error)
	Login(ctx context.Context, username, password string) (domain.User, error)
}

// userService 用户服务实现
type userService struct {
	regex    *regexp2.Regexp
	userRepo repository.UserRepository
}

// NewUserService 创建用户服务实例
func NewUserService(userRepo repository.UserRepository) UserService {
	passwordRegex, _ := regexp2.Compile(passwordRegexPattern, 0)
	return &userService{
		regex:    passwordRegex,
		userRepo: userRepo,
	}
}

// Register 用户注册实现
func (s *userService) Register(ctx context.Context, username, password string) (domain.User, error) {
	// 4. 对密码进行bcrypt加密
	hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
	if err != nil {
		return domain.User{}, err
	}

	// 5. 创建用户实体
	user := domain.User{
		Username: username,
		Password: string(hashedPassword),
		Nickname: generateRandomNickname(), // 生成随机昵称
	}

	// 6. 保存用户到数据库
	err = s.userRepo.Create(ctx, user)
	switch err {
	case repository.ErrDuplicateUsername:
		return domain.User{}, ErrDuplicateUsername
	case nil:
		u, err := s.userRepo.FindByUsername(ctx, user.Username)
		if err != nil {
			return domain.User{}, err
		}
		u.Password = ""
		return u, nil
	default:
		return domain.User{}, err
	}
}

// generateRandomNickname 生成随机昵称
func generateRandomNickname() string {
	// 初始化随机数生成器
	rand.Seed(time.Now().UnixNano())

	// 定义字母表
	letters := "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"

	// 生成四位随机字母
	randomLetters := make([]byte, 4)
	for i := range randomLetters {
		randomLetters[i] = letters[rand.Intn(len(letters))]
	}

	// 返回"绘图大师"+四位随机字母的格式
	return "绘图大师" + string(randomLetters)
}

// Login 用户登录实现
func (s *userService) Login(ctx context.Context, username, password string) (domain.User, error) {
	// 1. 根据用户名查找用户
	user, err := s.userRepo.FindByUsername(ctx, username)
	if err == repository.ErrRecordNotFound {
		return domain.User{}, ErrInvalidUsernameOrPassword
	}
	if err != nil {
		return domain.User{}, err
	}

	// 2. 验证密码
	err = bcrypt.CompareHashAndPassword([]byte(user.Password), []byte(password))
	if err != nil {
		return domain.User{}, ErrInvalidUsernameOrPassword
	}

	// 3. 清空密码后返回用户信息
	user.Password = ""
	return user, nil
}
